package com.haifeng.im.handler;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.haifeng.im.message.AuthRequest;
import com.haifeng.im.message.Message;
import org.apache.catalina.Authenticator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.framework.AopProxyUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import java.io.IOException;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;


public class MyHandler extends TextWebSocketHandler implements InitializingBean {
    private Logger logger = LoggerFactory.getLogger(getClass());

    private final Map<String, MessageHandler> HANDLERS = new HashMap<>();

    @Autowired
    private ApplicationContext applicationContext;

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws IOException {
        System.out.println("获取到消息 >> " + message.getPayload());
        logger.info("[handlemessage][session({})]接收到一条消息", session, message);
        // 获得消息类型

        if (message.getPayload().trim().startsWith("{")){
            JSONObject jsonmessage = JSON.parseObject(message.getPayload());
            String messagetype = jsonmessage.getString("type");
            //获得消息处理器
            MessageHandler messageHandler = HANDLERS.get(messagetype);

            if (messageHandler == null) {
                logger.error("[onmessage][消息类型({})]不存在消息处理器", message);
                return;
            }
            // 解析消息
            Class<? extends Message> messageclass = this.getMessageClass(messageHandler);
            // 处理消息
            Message messageobj = JSON.parseObject(jsonmessage.getString("body"), messageclass);
            messageHandler.execute(session, messageobj);
        }

    }

    /**
     * 建立连接时触发
     */
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        super.afterConnectionEstablished(session);
        logger.info("[afterconnectionEstablished][session({}) 接入]", session);
        // 解析 accessToken
        String accessToken = (String) session.getAttributes().get("accessToken");
        // 创建 AuthRequest 消息类型
        AuthRequest authRequest = new AuthRequest();
        authRequest.setAccessIoken(accessToken);
        // 获得消息处理器
        MessageHandler<AuthRequest> messageHandler = HANDLERS.get(AuthRequest.TYPE);
        if (messageHandler == null) {
            logger.error("[onOpen][认证消息类型，不存在消息处理器]");
            return;
        }
        messageHandler.execute(session, authRequest);
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        super.afterConnectionClosed(session, status);
        System.out.println("断开链接");

        String accessToken = (String) session.getAttributes().get("accessToken");
        // 创建 AuthRequest 消息类型
        AuthRequest authRequest = new AuthRequest();
        authRequest.setAccessIoken(accessToken);
        // 获得消息处理器
        MessageHandler<AuthRequest> messageHandler = HANDLERS.get(AuthRequest.TYPE);
        if (messageHandler == null) {
            logger.error("[onOpen][认证消息类型，不存在消息处理器]");
            return;
        }
        messageHandler.breaked(session, authRequest);

    }


    @Override
    public void afterPropertiesSet() throws Exception {
        // 通过 ApplicationContext 获得所有 MessageHandler Bean

        applicationContext.getBeansOfType(MessageHandler.class).values()
                .forEach(messageHandler -> HANDLERS.put(messageHandler.getType(),messageHandler));
        logger.info("[afterPropertiesSet][消息处理器数量：{}]",HANDLERS.size());
    }

    private Class<? extends Message> getMessageClass(MessageHandler handler){
        Class<?> targetClass= AopProxyUtils.ultimateTargetClass(handler);

        Type[] interfaces=targetClass.getGenericInterfaces();
        Class<?> superclass=targetClass.getSuperclass();
        while ((Objects.isNull(interfaces)||0==interfaces.length) && Objects.nonNull(superclass)){
            interfaces=superclass.getGenericInterfaces();
            superclass=targetClass.getSuperclass();
        }
        if (Objects.nonNull(interfaces)){
            for (Type type:interfaces){
                if (type instanceof ParameterizedType){
                    ParameterizedType parameterizedType= (ParameterizedType) type;
                    if (Objects.equals(parameterizedType.getRawType(),MessageHandler.class)){
                        Type[] actualTypeArguments=parameterizedType.getActualTypeArguments();
                        if (Objects.nonNull(actualTypeArguments) &&actualTypeArguments.length>0){
                            return (Class<? extends Message>) actualTypeArguments[0];
                        }else{
                            throw new IllegalStateException(String.format("类型(%s)获得不到消息类型",handler));
                        }
                    }
                }
            }
        }
        throw new IllegalStateException(String.format("类型(%s)获得不到消息类型",handler));
    }
}
